<?php

class Catalogue_AdminController extends Workset_Controller_Action_Admin {

	function init() {

		//загружаем модуль каталог
        Workset_Module::loadModule('catalogue');

		parent::init();

        $appHelper = new Catalogue_Helper_Application();
        Zend_Controller_Action_HelperBroker::addHelper($appHelper);

	}

    //главная страница админки
    function indexAction() {
        try {
			$this->_response->setRedirect('/catalogue/admin/list-category', 302);
		}
		catch (Exception $e) {
			$this->_response->setException($e);
		}
    }

    //добавление новой категории
    function addCategoryAction() {

        $parentId = (int)$this->_getParam('nodeid');

        $parentCategory = null;
        if ($parentId > 0) {
            $parentCategory = $this->_helper->application->getCategory($parentId);
        }

        $oper = $this->_getParam('oper');
        $outerEdit = !empty($oper) && $this->_request->isXmlHttpRequest() ? true : false;

        if ($outerEdit) {
            $this->_helper->viewRenderer->setNoRender(true);
        }

        $formConfig = $this->_helper->moduleConfig('forms/category');
        $form = new Catalogue_Form_Category($formConfig);

        //транслятор формы
        $form->setTranslator(
            $this->_translate,
            $this->_helper->moduleConfig->getConfig(array('lang', $this->_locale, 'validators'), null, true)
        );

        if ($this->_request->isPost()) {
            try {
                $post = $this->_request->getPost();

                //редактирование через внешнюю форму (jqGrid)
                if ($outerEdit) {
                    $post = $this->_helper->utils->addPrefix($post, 'category');
                }

                if ($form->isValid($post)) {
                    $values = $form->getValues();
                    $values = $this->_helper->utils->stripPrefix($values, 'category');
                    $category = Catalogue_Model_Category::create($values);

                    if ($parentCategory) {
                        $category->setParent($parentCategory);
                    }

                    $category->save();

                    if (!$this->_request->isXmlHttpRequest()) {
                        if ($category->hasParent()) {
                            $redirect = $this->_helper->url('list-category', null, null, array('nodeid' => $category->getParentId()));
                        } else {
                            $redirect = $this->_helper->url('list-category');
                        }
                        $this->_redirect($redirect);
                    } else {
                        return;
                    }
                }

				throw new Workset_Model_Exception($form->getCustomMessages(Workset_Form::ERROR_CODE), Workset_Form::ERROR_CODE);

            } catch (Zend_Exception $e) {
				$this->_helper->application->throwException($e, null, false);
            }
        }

        $this->view->form = $form;
    }

    //редактирование категории
    function editCategoryAction() {
        $categoryId = (int)$this->_getParam('id');

        $category = $this->_helper->application->getCategory($categoryId);
        if (!$category) {
            return;
        }

        $oper = $this->_getParam('oper');
        $outerEdit = !empty($oper) && $this->_request->isXmlHttpRequest() ? true : false;

        if ($outerEdit) {
            $this->_helper->viewRenderer->setNoRender(true);
        }

        $formConfig = $this->_helper->moduleConfig('forms/category');
        $form = new Catalogue_Form_Category($formConfig);

        if ($this->_request->isPost()) {
            try {
                $post = $this->_request->getPost();

                //редактирование через внешнбб форму (jqGrid)
                if ($outerEdit) {
                    $post = $this->_helper->utils->addPrefix($post, 'category');
                }

                if ($form->isValid($post)) {
                    $values = $form->getValues();
                    $values = $this->_helper->utils->stripPrefix($values, 'category');
                    $category->setData($values);
                    $category->save();

                    if (!$this->_request->isXmlHttpRequest()) {
                        if ($category->hasParent()) {
                            $redirect = $this->_helper->url('list-category', null, null, array('nodeid' => $category->getParentId()));
                        } else {
                            $redirect = $this->_helper->url('list-category');
                        }
                        $this->_redirect($redirect);
                    } else {
                        return;
                    }
                }

                throw new Workset_Model_Exception($form->getCustomMessages(Workset_Form::ERROR_CODE), Workset_Form::ERROR_CODE);

            } catch (Zend_Exception $e) {
                $this->_helper->application->throwException($e, null, false);
            }
        } else {
            $data = $category->toArray();
            foreach ($data as $key => $value) {
                $key = 'category_'.$key;
                if ($element = $form->getElement($key)) {
                    $element->setValue($value);
                }
            }
        }

        $this->view->form = $form;
        $this->render('add-category');
    }

    //удаление категории
    function deleteCategoryAction() {
        $this->_helper->viewRenderer->setNoRender(true);

        $listId = $this->_helper->application->getListId('id', true);
        if (empty($listId)) {
            throw $this->_helper->application->throwException(null, 404);
        }

        $filter = array('id in(?)' => $listId);

        $categoryList = Catalogue_Model_Category::getAll($filter);

        //проверка на возможность удаления
        foreach ($categoryList as $category) {
            if (!$category->isEmpty()) {
                throw $this->_helper->application->throwException(null, 500);
            }
        }

        //удаление
        try {
            foreach ($categoryList as $category) {
                $category->delete();
            }
        } catch (Zend_Exception $e) {
            throw $this->_helper->application->throwException($e);
        }

        //редирект
        if (!$this->_request->isXmlHttpRequest()) {
            if ($category->hasParent()) {
                $redirect = $this->_helper->url('list-category', null, null, array('nodeid' => $category->getParentId()));
            } else {
                $redirect = $this->_helper->url('list-category');
            }
            $this->_redirect($redirect);
        }

    }

	//список категорий
    function listCategoryAction() {
        $parentId = (int)$this->_getParam('nodeid');
        $refId = (int)$this->_getParam('ref');
        $backUrl = null;

        //url для формирования данных
        if (isset($this->_actionConfig['jqgrid_category_model_url'])) {
            $modelUrlParams = $this->_actionConfig['jqgrid_category_model_url'];
        } else {
            $modelUrlParams = array('action' => 'list-category-model');
        }

        //url для редактирования
        if (isset($this->_actionConfig['jqgrid_category_edit_url'])) {
            $editUrlParams = $this->_actionConfig['jqgrid_category_edit_url'];
        } else {
            $editUrlParams = array('action' => 'ajax-category-switcher');
        }

        //backurl для кнопки "назад"
        if (isset($this->_actionConfig['jqgrid_back_url'])) {
            $backUrlParams = $this->_actionConfig['jqgrid_back_url'];
        } else {
            $backUrlParams = null;
        }

        if ($parentId > 0) {
            $category = $this->_helper->application->getCategory($parentId);
            if (!$category) {
                return;
            }

            $modelUrlParams['params']['nodeid'] = $editUrlParams['params']['nodeid'] = $category->getId();

            $modelUrl = $this->_helper->url($modelUrlParams);
			$editUrl = $this->_helper->url($editUrlParams);

            if ($backUrlParams) {
                if ($refId > 0) {
                    $backUrlParams['params']['nodeid'] = $refId;
                    $backUrl = $this->_helper->url($backUrlParams);
                } else {
                    $backUrl = $this->_helper->url($backUrlParams);
                }
            }

            $reqParams = array('ref' => ($refId > 0 ? $refId : $parentId));

            if (!$this->_navigationInit && !$this->_getParam('navigationInit')) {

                $category->setUrl('navigation', $backUrl)->setLabel('navigation', $category['name']);
                $this->_addNavItem($category);
            }

        } else {
            $category = null;

            $modelUrl = $this->_helper->url($modelUrlParams);
			$editUrl = $this->_helper->url($editUrlParams);

            $reqParams = array();
        }

        //навигационная панель для грида
        $navGridEnabled = isset($this->_actionConfig['jqgrid_category_navgrid']) && false !== $this->_actionConfig['jqgrid_category_navgrid'];
        $navGridButtons = null;
        $navGridMyButtons = null;

        if ($navGridEnabled) {
            $navGridButtons = (array)$this->_actionConfig['jqgrid_category_navgrid'];

            if (!empty($this->_actionConfig['jqgrid_category_navgrid_buttons']) && is_array($this->_actionConfig['jqgrid_category_navgrid_buttons'])) {
                $navGridMyButtons = $this->_actionConfig['jqgrid_category_navgrid_buttons'];
            }
        }

        $gridOptions = array(
            'caption' => $this->_actionConfig['jqgrid_category_caption'],
            'url' => $modelUrl,
            'mtype' => 'GET',
            'colNames' => array_values($this->_actionConfig['jqgrid_category_col_names']),
            'colModel' => array_values($this->_actionConfig['jqgrid_category_col_model']),
            'sortname' => 'id',
            'sortorder' => "desc",
            'viewrecords' => true,
            'multiselect' => true,
            'editurl'   => $editUrl,
            'treeGrid' => true,
            'treeGridModel' => 'adjacency',
            'treedatatype' => 'json',
            'ExpandColumn' => 'name',
            'ExpandColClick' => true,
            'autowidth' => true,
            'rowNum' => 100,
            'viewsortcols' => array('name', 'display_title', 'code', 'id'),
			'ondblClickRow' => new Zend_Json_Expr($this->_helper->application->jsFunction('ondblClickRow', array('rowId'), true)),
			'gridComplete' => new Zend_Json_Expr($this->_helper->application->jsFunction('gridComplete', array(
				'opt' => array(
					'buttons' => $navGridMyButtons,
					'qdata' => $reqParams ? $reqParams : null,
				)
			), true)),
        );

        //ссылка на объект помошника
        $this->view->grid = $this->view
                ->JQueryGrid()
                ->setTableId('categoryList')
                ->setPagerId('categoryPager')
                ->setOptions($gridOptions);

        if ($navGridEnabled) {
            $this->view->grid->enableNavGrid($navGridButtons);
        }

		$this->view->grid->jsObject = $this->_helper->application->jsFunctionName();

        //родительская категория
        $this->view->category = $category;

        //ссылка на верхний уровень вложенности
        if ($backUrl) {
            $this->view->backurl = $backUrl;
            $this->view->backurlLabel = $this->_actionConfig['backurl_label'];
        }

        if (!empty($this->_actionConfig['view_script'])) {
            $this->render($this->_actionConfig['view_script']);
        }
    }

    function listCategoryModelAction() {
        $parentId = (int)$this->_getParam('nodeid');

        $page = (int)$this->_getParam('page');
        if ($page < 1) {
           $page = 1;
        }

        $rows = (int)$this->_getParam('rows');
        if ($rows < 1) {
            $rows = Workset_Model_Object_Abstract::ROWS_LIMIT;
        }

        //выбирать только несовпадающие элементы
        $diff = $this->_getParam('diff');
        if ($diff) {
            $diff = $this->_helper->application->getListId($diff);
        }

        //выбирать только совпадающие элементы
        $intersect = $this->_getParam('intersect');
        if ($intersect) {
            $intersect = $this->_helper->application->getListId($intersect);
        }

        //глубина вложенности
		$level = $this->_getParam('n_level');

		if (!isInt($level)) {
			$level = 0;
		} else {
			$level += 1;
		}

        $cols = $this->_helper->application->getList('cols', true);
        $order = $this->_helper->application->getSortOrder();

		$filter = $this->_getParam('filters');
		$filter = $this->_helper->JQueryGrid->getFilter($filter, $this->_actionConfig['jqgrid_category_col_model']);

        if ($diff) {
            $filter['id not in(?)'] = $diff;
        }

        if ($intersect) {
            $filter['id in(?)'] = $intersect;
        }

        if ($parentId > 0) {
            $category = $this->_helper->application->getCategory($parentId);
            $categoryList = $category->getChilds($filter, $order, $rows, $page, true);
        } else {
			$level = 0;
            $category = null;
            $filter[] = 'parent_id is null';
            $categoryList = Catalogue_Model_Category::getAll($filter, $order, $rows, $page, true);
        }

        $colNames = $this->_helper->utils->arrayValues(
            $this->_actionConfig['jqgrid_category_col_model'], 'index', 1
        );

        if ($cols) {
            $cols = array_intersect($colNames, $cols);
        } else {
            $cols = $colNames;
        }

        $records = $this->_helper->JQueryGrid(
            $categoryList, $page, ceil($categoryList->getTotalCount() / $rows),
            $categoryList->getTotalCount(), $cols
        );

        $categoryList = $categoryList->setKeyIndex('id')->toArray();

        foreach ($records['rows'] as $key => &$record) {
            $category = $categoryList[$record['id']];
            $record['cell'] = array_merge($record['cell'], array(
                $level,
                $category->hasParent() ? $category->getParentId() : 'null',
                !$category->hasChilds(),
                false
            ));
        }

        $this->_helper->json($records, true);
        //echo Zend_Json::encode($records);
    }

	function listCategoryModelCustomAction() {

		$this->_helper->viewRenderer->setNoRender(true);

		$config = $this->_actionConfig;
		$config['access_checked'] = true;

		Zend_Registry::set('actionConfig', $config);

        $parentId = (int)$this->_getParam('nodeid');

		$params = array();

		if ($parentId > 0) {
			$params['nodeid'] = $parentId;

		} elseif (!empty($this->_actionConfig['category_code'])) {

			$category = Catalogue_Model_Category::getByCode($this->_actionConfig['category_code'])->current();
			if (!$category) {
				$this->_helper->application->throwException('Undefined category ' . $code);
				return;
			}
            $params['nodeid'] = $category->getId();

		} elseif (!empty($this->_actionConfig['category_id'])) {

			$params['nodeid'] = (int)$this->_actionConfig['category_id'];

		}

		$this->_forward('list-category-model', null, null, $params);
	}

    function selectSingleCategoryAction() {
        $parentId = (int)$this->_getParam('nodeid');
        $backurl = $this->_getParam('backurl');
        $filter = array();

        if ($parentId > 0) {
            $filter["parent_id = ?"] = $parentId;
        }

        if (!$backurl) {
            $backurl = $this->_request->getRequestUri();
        }

        $uri = $this->_helper->httpUri($backurl);
		$redirectParams = $uri->getQueryAsArray();

		$uri->setQuery(null);
		$redirectUrl = $uri->getUri();

		$modelUrl = $this->_helper->url('list-category-model');

		$gridOptions = array(
            'caption' => 'Список',
            'url' => $modelUrl,
            'mtype' => 'GET',
            'colNames' => array_values($this->_actionConfig['jqgrid_category_col_names']),
            'colModel' => array_values($this->_actionConfig['jqgrid_category_col_model']),
            'sortname' => 'id',
            'sortorder' => "desc",
            'viewrecords' => true,
			'treeGrid' => true,
            'treeGridModel' => 'adjacency',
            'treedatatype' => 'json',
            'ExpandColumn' => 'name',
            'ExpandColClick' => true,
            'autowidth' => true,
            'rowNum' => 50,
            'viewsortcols' => array('name', 'display_title', 'code', 'id'),
			'ondblClickRow' => new Zend_Json_Expr($this->_helper->application->jsFunction('selectRow', array('id'), true)),
        );

		$tableId = 'categoryList';
        $pageId = 'categoryPager';

        //ссылка на объект помошника
        $this->view->grid = $this->view
                ->JQueryGrid()
                ->setTableId($tableId)
                ->setPagerId($pageId)
                ->setOptions($gridOptions)
				->enableNavGrid(array(
                    'edit' => false,
					'add' => false,
					'del' => false
                ))
				->addNavButton('btn_select', array(
                    'buttonicon' => 'ui-icon-circle-check',
                    'caption' => 'Выбрать',
                    'position' => 'last',
                    'onClickButton' => new Zend_Json_Expr($this->_helper->application->jsFunction('selectSingleRow', null, true)),
                ));

		$this->view->jsObject = $this->_helper->application->jsFunctionName();
		$this->view->redirectUrl = $redirectUrl;
		$this->view->redirectParams = Zend_Json::encode($redirectParams);

		$this->render('select-category');

    }

	function selectMultiCategoriesAction() {
		$parentId = (int)$this->_getParam('nodeid');
        $backurl = $this->_getParam('backurl');
        $filter = array();

        if ($parentId > 0) {
            $filter["parent_id = ?"] = $parentId;
        }

        if (!$backurl) {
            $backurl = $this->_request->getRequestUri();
        }

        $uri = $this->_helper->httpUri($backurl);
		$redirectParams = $uri->getQueryAsArray();

		$uri->setQuery(null);
		$redirectUrl = $uri->getUri();

		$modelUrl = $this->_helper->url('list-category-model');

		$gridOptions = array(
            'caption' => 'Список',
            'url' => $modelUrl,
            'mtype' => 'GET',
            'colNames' => array_values($this->_actionConfig['jqgrid_category_col_names']),
            'colModel' => array_values($this->_actionConfig['jqgrid_category_col_model']),
            'sortname' => 'id',
            'sortorder' => "desc",
            'viewrecords' => true,
            'autowidth' => true,
			'multiselect' => true,
            'rowNum' => 50,
            'viewsortcols' => array('name', 'display_title', 'code', 'id'),
        );

		$tableId = 'categoryList';
        $pageId = 'categoryPager';

        //ссылка на объект помошника
        $this->view->grid = $this->view
                ->JQueryGrid()
                ->setTableId($tableId)
                ->setPagerId($pageId)
                ->setOptions($gridOptions)
				->enableNavGrid(array(
                    'edit' => false,
					'add' => false,
					'del' => false
                ))
				->addNavButton('btn_select', array(
                    'buttonicon' => 'ui-icon-circle-check',
                    'caption' => 'Выбрать',
                    'position' => 'last',
                    'onClickButton' => new Zend_Json_Expr($this->_helper->application->jsFunction('selectMultiRows', null, true)),
                ));

		$this->view->jsObject = $this->_helper->application->jsFunctionName();
		$this->view->redirectUrl = $redirectUrl;
		$this->view->redirectParams = Zend_Json::encode($redirectParams);

		$this->render('select-category');
	}

    //создает новый атрибут
    function addAttrAction() {
        $oper = $this->_getParam('oper');
        $outerEdit = !empty($oper) && $this->_request->isXmlHttpRequest() ? true : false;

        if ($outerEdit) {
            $this->_helper->viewRenderer->setNoRender(true);
        }

        $formConfig = $this->_helper->moduleConfig('forms/attribute');
        $form = new Catalogue_Form_Attribute($formConfig);

        //транслятор формы
        $form->setTranslator(
            $this->_translate,
            $this->_helper->moduleConfig->getConfig(array('lang', $this->_locale, 'validators'), null, true)
        );

        if ($this->_request->isPost()) {
            try {
                $post = $this->_request->getPost();

                //редактирование через внешнюю форму (jqGrid)
                if ($outerEdit) {
                    $post = $this->_helper->utils->addPrefix($post, 'attr');
                }

                if ($form->isValid($post)) {
                    $values = $form->getValues();
                    $values = $this->_helper->utils->stripPrefix($values, 'attr');

                    $attr = Catalogue_Model_Attribute::create($values);
                    $attr->save();

                    if (!$this->_request->isXmlHttpRequest()) {
                        $this->_helper->redirector->gotoSimple('list-attr');
                    } else {
                        return;
                    }
                }

                throw new Workset_Model_Exception($form->getCustomMessages(Workset_Form::ERROR_CODE), Workset_Form::ERROR_CODE);

            } catch (Zend_Exception $e) {
                $this->_helper->application->throwException($e, null, false);
            }
        }

        if (!$outerEdit) {
            $this->view->form = $form;
            $this->view->backurl = $this->_helper->url('list-attr');
        }
    }

    //редактирование атрибута
    function editAttrAction() {
        $attrId = (int)$this->_getParam('id');

        $attr = $this->_helper->application->getAttribute($attrId);

        $oper = $this->_getParam('oper');
        $outerEdit = !empty($oper) && $this->_request->isXmlHttpRequest() ? true : false;

        if ($outerEdit) {
            $this->_helper->viewRenderer->setNoRender(true);
        }

        $formConfig = $this->_helper->moduleConfig('forms/attribute');
        $form = new Catalogue_Form_Attribute($formConfig);

        //транслятор формы
        $form->setTranslator(
            $this->_translate,
            $this->_helper->moduleConfig->getConfig(array('lang', $this->_locale, 'validators'), null, true)
        );

        if ($this->_request->isPost()) {
            try {
                $post = $this->_request->getPost();

                //редактирование через внешнюю форму (jqGrid)
                if ($outerEdit) {
                    $post = $this->_helper->utils->addPrefix($post, 'attr');
                }

                if ($form->isValid($post)) {
                    $values = $form->getValues();
                    $values = $this->_helper->utils->stripPrefix($values, 'attr');
                    $attr->setData($values);
                    $attr->save();

                    if (!$this->_request->isXmlHttpRequest()) {
                        $this->_helper->redirector->gotoSimple('list-attr');
                    } else {
                        return;
                    }
                }

                throw new Workset_Model_Exception($form->getCustomMessages(Workset_Form::ERROR_CODE), Workset_Form::ERROR_CODE);

            } catch (Zend_Exception $e) {
                $this->_helper->application->throwException($e, null, false);
            }
        } else {
            $data = $attr->toArray();
            foreach ($data as $key => $value) {
                $key = 'attr_'.$key;
                if ($element = $form->getElement($key)) {
                    $element->setValue($value);
                }
            }
        }

        if (!$outerEdit) {
            $this->view->form = $form;
            $this->view->backurl = $this->_helper->url('list-attr');
            $this->render('add-attr');
        }
    }

    //удаляет атрибут
    function deleteAttrAction() {
        $this->_helper->viewRenderer->setNoRender(true);

        $listId = $this->_helper->application->getListId('id', true);
        if (empty($listId)) {
            throw $this->_helper->application->throwException(null, 404);
        }

        $filter = array('id in(?)' => $listId);

        $attrList = Catalogue_Model_Attribute::getAll($filter);

        //удаление
        try {
            foreach ($attrList as $attr) {
                $attr->delete();
            }
        } catch (Zend_Exception $e) {
            throw $this->_helper->application->throwException($e);
        }

        //редирект
        if (!$this->_request->isXmlHttpRequest()) {
            $this->_helper->redirector->gotoSimple('list-attr');
        }
    }

    function listAttrAction() {

        $modelUrl = $this->_helper->url('list-attr-model');
		$modelAttrItemsUrl = $this->_helper->url('list-attr-item-model');

        $gridOptions = array(
            'caption' => $this->_actionConfig['jqgrid_attr_caption'],
            'url' => $modelUrl,
            'mtype' => 'GET',
            'colNames' => array_values($this->_actionConfig['jqgrid_attr_col_names']),
            'colModel' => array_values($this->_actionConfig['jqgrid_attr_col_model']),
            'sortname' => 'id',
            'sortorder' => "desc",
            'viewrecords' => true,
            'multiselect' => true,
            'editurl'   => $this->_helper->url('ajax-attr-switcher'),
            'autowidth' => true,
            'rowNum' => 20,
            'viewsortcols' => array('name', 'display_title', 'code', 'id'),
            'subGrid' => true,
            'subGridRowExpanded' => new Zend_Json_Expr($this->_helper->application->jsFunction('expand', array('subgrid_id', 'row_id'), true)),
        );

		//опции для списка значений атрибута (для enum атрибутов)
		$subGridOptions = array(
			'url' => $modelAttrItemsUrl,
			'datatype' => 'json',
			'mtype' => 'GET',
			'colNames' => $this->_actionConfig['jqgrid_attr_item_col_names'],
			'colModel' => $this->_actionConfig['jqgrid_attr_item_col_model'],
			'sortname' => 'id',
            'sortorder' => "desc",
            'viewrecords' => true,
			'multiselect' => true,
			'autowidth' => true,
			'height' => '100%',
			'editurl' => $this->_helper->url('ajax-attr-item-switcher')
		);

        //ссылка на объект помошника
        $this->view->grid = $this->view->JQueryGrid()
                                       ->setTableId('attrList')
                                       ->setPagerId('attrPager')
                                       ->setOptions($gridOptions)
                                       ->enableNavGrid(array(
											'search' => true
										));
		//ссылка на sub-grid
		$this->view->subgrid = $this->view->JQueryGrid()
										  ->getNewInstance()
										  ->setTableId('attrItemList')
                                          ->setPagerId('attrItemPager')
										  ->setOptions($subGridOptions)
										  ->enableNavGrid();

		$this->view->grid->jsObject = $this->_helper->application->jsFunctionName();

        if (!empty($this->_actionConfig['view_script'])) {
            $this->render($this->_actionConfig['view_script']);
        }

    }

    function listAttrModelAction() {
        $diffId = (int)$this->_getParam('diff');
        $intersectId = (int)$this->_getParam('intersect');

        $page = (int)$this->_getParam('page');
        if ($page < 1) {
           $page = 1;
        }

        $rows = (int)$this->_getParam('rows');
        if ($rows < 1) {
            $rows = Workset_Model_Object_Abstract::ROWS_LIMIT;
        }

        $order = $this->_helper->application->getSortOrder(null, null, false, false);

		$filter = $this->_getParam('filters');
		$filter = $this->_helper->JQueryGrid->getFilter($filter, $this->_actionConfig['jqgrid_attr_col_model']);

        $colNames = $this->_helper->utils->arrayValues(
            $this->_actionConfig['jqgrid_attr_col_model'], 'index', 1
        );

        $cols = $this->_helper->application->getList('cols', true);

        if ($cols) {
            $cols = array_intersect($colNames, $cols);
        } else {
            $cols = $colNames;
        }

        if ($intersectId > 0 || $diffId > 0) {
            $id = $intersectId > 0 ? $intersectId : $diffId;
            $category = $this->_helper->application->getCategory($id);

            if ($intersectId > 0) {
               	$attrList = $category->getAttributes($filter, $order, $rows, $page);
            } else {
				$attrs = $category->getAttributes();
				if ($attrs->count() > 0) {
					$filter['id not in(?)'] = $attrs->toArray('id');
				}
				$attrList = Catalogue_Model_Attribute::getAll($filter, $order, $rows, $page, true);
            }
        } else {
            $attrList = Catalogue_Model_Attribute::getAll($filter, $order, $rows, $page, true);
        }

        $records = $this->_helper->JQueryGrid(
            $attrList, $page, ceil($attrList->getTotalCount() / $rows),
            $attrList->getTotalCount(), $cols
        );

        $this->_helper->json($records, true);
        //echo Zend_Json::encode($records);
    }

    function addAttrItemAction() {
        $this->_helper->viewRenderer->setNoRender(true);

        $attr = $this->_helper->application->getAttribute('id', true, true);

        $valuePostKey = 'value';

        $formConfig = $this->_helper->moduleConfig('forms/attribute_item');
		$form = new Catalogue_Form_AttributeItem($formConfig);

        //транслятор формы
        $form->setTranslator(
            $this->_translate,
            $this->_helper->moduleConfig->getConfig(array('lang', $this->_locale, 'validators'), null, true)
        );

        if ($this->_request->isPost()) {
            $post = $this->_request->getPost();
            if (!isset($post[$valuePostKey])) {
                throw $this->_helper->application->throwException(null, 404);
            }

            if ($form->isValid($post)) {
                try {
                    $values = $form->getValues();
                    $attr->addItem($values);

                    if (!$this->_request->isXmlHttpRequest()) {
                        $redirect = $this->_helper->url('list-attr');
                        $this->_redirect($redirect);
                    } else {
                        return;
                    }

					throw new Workset_Model_Exception($form->getCustomMessages(Workset_Form::ERROR_CODE), Workset_Form::ERROR_CODE);

                } catch (Zend_Exception $e) {
                    throw $this->_helper->application->throwException($e, null, false);
                }
            }
        }
    }

    //редактирование значения атрибута (enum)
    function editAttrItemAction() {
        $this->_helper->viewRenderer->setNoRender(true);

        $itemId = $this->_request->getPost('id');

        $item = $this->_helper->application->getAttrItem($itemId);

        $attr = $item->getAttribute();

        $formConfig = $this->_helper->moduleConfig('forms/attribute_item');
		$form = new Catalogue_Form_AttributeItem($formConfig);

        //транслятор формы
        $form->setTranslator(
            $this->_translate,
            $this->_helper->moduleConfig->getConfig(array('lang', $this->_locale, 'validators'), null, true)
        );

        if ($this->_request->isPost()) {
            try {
                $post = $this->_request->getPost();
                if ($form->isValid($post)) {
                    $values = $form->getValues();
                    $attr->changeItem($item, $values);

                    if (!$this->_request->isXmlHttpRequest()) {
                        $redirect = $this->_helper->url('list-attr');
                        $this->_redirect($redirect);
                    } else {
                        return;
                    }
                }

				throw new Workset_Model_Exception($form->getCustomMessages(Workset_Form::ERROR_CODE), Workset_Form::ERROR_CODE);

            } catch (Zend_Exception $e) {
               throw $this->_helper->application->throwException($e, null, false);
            }
        }
    }

    //удаляет новое значение атрибута типа список
    function deleteAttrItemAction() {
        $this->_helper->viewRenderer->setNoRender(true);

        $reqId = $this->_request->getPost('id');
        $listId = $this->_helper->application->getListId($reqId);
        if (empty($listId)) {
            throw $this->_helper->application->throwException(null, 404);
        }

        $attr = $this->_helper->application->getAttribute('id', true, true);

        $filter = array('id in(?)' => $listId);
        $itemList = Catalogue_Model_Attribute_Enum_Item::getAll($attr, $filter);

        try {
            foreach ($itemList as $item) {
                $item->delete();
            }
        } catch (Zend_Exception $e) {
            throw $this->_helper->application->throwException($e);
        }

        if (!$this->_request->isXmlHttpRequest()) {
            $redirect = $this->_helper->url('list-attr');
            $this->_redirect($redirect);
        } else {
            return;
        }
    }

    //список значений атрибота типа список
    function listAttrItemAction() {
        throw $this->_helper->application->throwException('Not implemented', 500);
    }

	function listAttrItemModelAction() {

        $attr = $this->_helper->application->getAttribute('id', true, true);

        $page = (int)$this->_getParam('page');
        if ($page < 1) {
           $page = 1;
        }

        $rows = (int)$this->_getParam('rows');
        if ($rows < 1) {
            $rows = Workset_Model_Object_Abstract::ROWS_LIMIT;
        }

        $order = $this->_helper->application->getSortOrder(null, null, false, false);

		$filter = null;

		$items = $attr->getItems($filter, $order, $rows, $page, true);

        $records = $this->_helper->JQueryGrid(
            $items, $page, ceil($items->getTotalCount() / $rows),
            $items->getTotalCount(), array('value', 'id')
        );

        $this->_helper->json($records, true);
	}

    //добавляет атрибут к категории
    function addCategoryAttrAction() {
        $this->_helper->viewRenderer->setNoRender(true);

        $category = $this->_helper->application->getCategory('nodeid', true);
        $attr = $this->_helper->application->getAttribute('id', true);

		try {

            //добавляем категорию в конец списка
			$data = array('priority' => $category->getMaxAttributePriority() + 1);
			$category->addAttribute($attr, $data);

		} catch (Zend_Exception $e) {
			throw $this->_helper->application->throwException($e);
		}

		if (!$this->_request->isXmlHttpRequest()) {
			$redirect = $this->_helper->url('list-category-attr', null, null, array('nodeid' => $category->getId()));
			$this->_redirect($redirect);
		}
    }

    //удаляет атрибут из категории
    function deleteCategoryAttrAction() {
        $this->_helper->viewRenderer->setNoRender(true);

        $category = $this->_helper->application->getCategory('nodeid', true);
        $attr = $this->_helper->application->getAttribute('id', true);

        try {

            $observer = new Catalogue_Model_Category_Observer_AttributePriority();

            $category->attach($observer);
			$category->deleteAttribute($attr);

		} catch (Zend_Exception $e) {
			throw $this->_helper->application->throwException($e);
		}

        if (!$this->_request->isXmlHttpRequest()) {
			$redirect = $this->_helper->url('list-category-attr', null, null, array('nodeid' => $category->getId()));
			$this->_redirect($redirect);
		}
    }

    function sortCategoryAttrAction() {
        $this->_helper->viewRenderer->setNoRender(true);

        $index = (int)$this->_getParam('index');
        if ($index < 1) {
            throw $this->_helper->application->throwException(null, 500);
        }

		$category = $this->_helper->application->getCategory('id', true);
        $attr = $this->_helper->application->getAttribute('nodeid', true);

        $category->setAttributePriority($attr, $index);

        if (!$this->_request->isXmlHttpRequest()) {
            $redirect = $this->_getParam('backurl');
            if (!$redirect) {
                $redirect = $this->_helper->url('list-category-attr', null, null, array(
                    'nodeid' => $category->getId()
                ));
            }
            $this->_redirect($redirect);
        }

    }

    //список атрибутов категории
    function listCategoryAttrAction() {
        $category = $this->_helper->application->getCategory('nodeid', true);

        $refId = (int)$this->_getParam('ref');

		if (!empty($this->_actionConfig['jqgrid_add_attr_url'])) {
			$saveAttrUrl = $this->_helper->url($this->_actionConfig['jqgrid_add_attr_url']);
		} else {
			$saveAttrUrl = $this->_helper->url('add-category-attr');
		}

		if (!empty($this->_actionConfig['jqgrid_delete_attr_url'])) {
			$deleteAttrUrl = $this->_helper->url($this->_actionConfig['jqgrid_delete_attr_url']);
		} else {
			$deleteAttrUrl = $this->_helper->url('delete-category-attr');
		}

		if (!empty($this->_actionConfig['jqgrid_back_url'])) {
			$backUrlParams = $this->_actionConfig['jqgrid_back_url'];
		} else {
			$backUrlParams = array(
				'action' => 'list-category'
			);
		}

		if ($refId > 0) {
			$backUrlParams['params']['nodeid'] = $refId;
        }

		$backUrl = $this->_helper->url($backUrlParams);

		//показываем только заданные в конфиге столбцы
        if (!empty($this->_actionConfig['jqgrid_visible_attr_col_model'])) {
            $this->_actionConfig['jqgrid_attr_col_model'] = array_values(array_intersect_key($this->_actionConfig['jqgrid_attr_col_model'], array_flip($this->_actionConfig['jqgrid_visible_attr_col_model'])));
            $this->_actionConfig['jqgrid_attr_col_names'] = array_values(array_intersect_key($this->_actionConfig['jqgrid_attr_col_names'], array_flip($this->_actionConfig['jqgrid_visible_attr_col_model'])));
        }

		$displayCols = $this->_helper->utils->arrayValues($this->_actionConfig['jqgrid_attr_col_model'], 'index', 1);

		if (!empty($this->_actionConfig['jqgrid_attr_model_url'])) {

			$selAttrModelUrlParams = array_merge(
				$this->_actionConfig['jqgrid_attr_model_url'],
				array('params' => array(
					'intersect' => $category->getId(),
					'cols' => implode(',', $displayCols)
				))
			);

			$attrModelUrlParams = array_merge(
				$this->_actionConfig['jqgrid_attr_model_url'],
				array('params' => array(
					'diff' => $category->getId(),
            		'cols' => implode(',', $displayCols)
				))
			);

		} else {

			$selAttrModelUrlParams = array(
				'action' => 'list-attr-model',
				'params' => array(
					'intersect' => $category->getId(),
					'cols' => implode(',', $displayCols)
				)
			);

			$attrModelUrlParams = array(
				'action' => 'list-attr-model',
				'params' => array(
					'diff' => $category->getId(),
            		'cols' => implode(',', $displayCols)
				)
			);
		}

		if (!empty($this->_actionConfig['jqgrid_attr_edit_url'])) {
			$editUrl = $this->_helper->url($this->_actionConfig['jqgrid_attr_edit_url']);
		} else {
			$editUrl = $this->_helper->url('ajax-attr-switcher');
		}

 		$selectedAttrModelUrl = $this->_helper->url($selAttrModelUrlParams);

        $allAttrModelUrl = $this->_helper->url($attrModelUrlParams);

		$category->setUrl('navigation', $backUrl)->setLabel('navigation', $category['name']);

        $initNav = $this->_navigationInit || $this->_getParam('navigationInit');

		if (!$initNav) {

			$this->_addNavItem($category);
			$this->_addNavItem(array(
				'title' => 'title',
				'label' => 'title',
				'action' => $this->_request->getActionName(),
				'controller' => $this->_request->getControllerName(),
				'module' => $this->_request->getModuleName(),
				'active' => true
			));
		}

        $selectedAttrOptions = array(
            'caption' => $this->_actionConfig['jqgrid_selected_attr_caption'],
            'url' => $selectedAttrModelUrl,
            'prmNames' => array(
                'page' => 'page',
                'rows' => null,
                'totalrows' => 'totalrows',
                'nd' => 'nd',
                'id' => 'id',
                'sort' => null,
                'order' => null,
            ),
            'mtype' => 'GET',
            'colNames' => $this->_actionConfig['jqgrid_attr_col_names'],
            'colModel' => $this->_actionConfig['jqgrid_attr_col_model'],
            'sortname' => 'sort',
            'sortorder' => "asc",
            'viewrecords' => true,
            'editurl'   => $editUrl,
            'autowidth' => true,
            'viewsortcols' => array('ID'),
            'height' => 300,
            'gridComplete' => new Zend_Json_Expr(
                $this->_helper->application->jsFunction('gridComplete', array(
                    'categoryId' => $category->getId(),
                    'url' => $this->_helper->url('sort-category-attr')
                ), true)
            )
        );

        $allAttrOptions = array(
            'caption' => $this->_actionConfig['jqgrid_attr_caption'],
            'url' => $allAttrModelUrl,
            'mtype' => 'GET',
            'colNames' => $this->_actionConfig['jqgrid_attr_col_names'],
            'colModel' => $this->_actionConfig['jqgrid_attr_col_model'],
            'sortname' => 'id',
            'sortorder' => "desc",
            'viewrecords' => true,
            'editurl'   => $editUrl,
            'autowidth' => true,
            'rowNum' => 20,
            'height' => 300,
            'viewsortcols' => array('name', 'display_title', 'code', 'id'),
        );

        $selectedAttrId = 'categoryAttrList';
        $allAttrId = 'allAttrList';
        $pageId = 'attrPager';
        $selPageId = 'categoryPager';

        //ссылка на объект помошника
        $allGrid = $this->view->JQueryGrid();

        $selectedGrid = $allGrid->getNewInstance();
		$selectedGrid	->setTableId($selectedAttrId)
						->setOptions($selectedAttrOptions)
						->setPagerId($selPageId)
						->enableNavGrid(array(
							'edit' => false,
							'add' => false,
							'del' => false,
						))
						->invokeParams(array(
							'nodeid' => $category->getId(),
							'url' => $deleteAttrUrl
						))
						->addMethod('gridDnD', array(
							'connectWith' => '#'.$allAttrId,
							'ondrop' => new Zend_Json_Expr(
								$this->_helper->application->jsFunction(
									'removeItem',
									array('evt', 'context'),
									true
								)
							),
						))
						->gridComplete(false);

        $allGrid->setTableId($allAttrId)
                ->setPagerId($pageId)
                ->setOptions($allAttrOptions)
                ->enableNavGrid(array(
					'edit' => false,
					'add' => false,
					'del' => false,
				))
				->invokeParams(array(
					'nodeid' => $category->getId(),
					'url' => $saveAttrUrl
				))
				->addMethod('gridDnD', array(
					'connectWith' => '#'.$selectedAttrId,
					'ondrop' => new Zend_Json_Expr(
						$this->_helper->application->jsFunction(
							'addItem',
							array('evt', 'context'),
							true
						)
					),
				))
				->gridComplete(false);

        $this->view->selectedGrid = $selectedGrid;
        $this->view->allGrid = $allGrid;
        $this->view->category = $category;
        $this->view->backurl = $backUrl;
        $this->view->backurlLabel = $this->_actionConfig['backurl_label'];

		$this->view->jsObject = $this->_helper->application->jsFunctionName();
    }

    /**
     * @throws Zend_Exception
     * @return void
     *
     * request params:
     *
     * nodeid - ID или массив ID категорий объекта
     * multi - тип привязки (0 - единственная привязка, 1 - множественная)
     */
    function addObjectAction() {
        $oper = $this->_getParam('oper');
        $outerEdit = !empty($oper) && $this->_request->isXmlHttpRequest() ? true : false;

        $backurl = $this->_getParam('backurl');
		$attrPrefix = Catalogue_Form_Object::ATTR_PREFIX;
        $reqParamCategory = 'nodeid';
        $attrs = array();
        $files = array();
		$uploadFiles = false;

        if ($outerEdit) {
            $this->_helper->viewRenderer->setNoRender(true);
        }

        //ID выбранных категорий
        $categoryIds = $this->_helper->application->getListId($reqParamCategory, true);

        //Предлагаем выбрать категорию
        if (empty($categoryIds)) {
            $uri = $this->_helper->httpUri($this->_request->getRequestUri());
			$uri->addReplaceQueryParameters(array('multi' => 0));

			$this->view->selectSingleCategoryUrl = $this->_helper->url('select-single-category', null, null, array(
                'backurl' => $uri->getUri(),
            ));

			$uri->addReplaceQueryParameters(array('multi' => 1));
            $this->view->selectMultiCategoryUrl = $this->_helper->url('select-multi-categories', null, null, array(
                'backurl' => $uri->getUri()
            ));

            $this->render('add-object-select-category');
            return;
        }

        //тип привязки объекта к категории (0 - базовая категория, 1 - множественная привязка)
        if ($this->_getParam('multi') == 1) {
            $multiCategories = true;
        } else {
            $multiCategories = false;
        }

        //список категорий, к которым привязан объект
        $objectCategories = array();

        if (!$multiCategories) {
            $objectCategory = $this->_helper->application->getCategory($categoryIds[0]);

            //дефолтовый список категорий из настроек
			$objectCategories = $this->_helper->application->getDefaultCategories($objectCategory);
            $objectCategories[$objectCategory->getId()] = $objectCategory;

			//пункт в навигации
			$objectCategory->setUrl('navigation', '#')->setLabel('navigation', $objectCategory['name']);
			$this->_addNavItem($objectCategory);
        } else {
			$objectCategory = null;
            $objectCategories = Catalogue_Model_Category::getAll(array(
               "id in(?)" => $categoryIds
            ))->setKeyIndex('id')->toArray();
        }

		//нельзя создать объект без привязки к категории
        if (empty($objectCategories)) {
            throw $this->_helper->application->throwException('Категории не выбраны', 404);
        }

        $formConfig = $this->_helper->moduleConfig('forms/object');
		$form = new Catalogue_Form_Object($formConfig);

        //сохраним  категорию в форме
        $form->addActionParams(array('multi' => (int)$multiCategories))
             ->setCategory($categoryIds, $reqParamCategory)
		     ->addEditModes(array(
                    Catalogue_Form_Object::SAVE_MODE,
                    Catalogue_Form_Object::APPLY_MODE
                ));

        //транслятор формы
        $form->setTranslator(
            $this->_translate,
            $this->_helper->moduleConfig->getConfig(array('lang', $this->_locale, 'validators'), null, true)
        );

        //установим атрибуты
        $attrs = Catalogue_Model_Category::getCategoryAttributes($objectCategories, true);

        //значения атрибутов
		foreach ($attrs as $categoryId => $attrsGroup) {

            $form->addAttrFieldGroup($objectCategories[$categoryId]['code'], null, array(
                'legend' => $objectCategories[$categoryId]['name']
            ));

    		foreach ($attrsGroup as $id => $attr) {

                $form->addAttrField($attr);
                $form->addAttrToGroup($objectCategories[$categoryId]['code'], $attr);

                if ($attr->isFile()) {
                    if (!$uploadFiles) {
                        $uploadFiles = true;
                    }
                }

                if ($attr->isMultiple() && !$attr->isEnum()) {
                    $form->addAttrFieldButton($attr, 'add');
                    $form->addAttrFieldButton($attr, 'del');
                }
			}
		}

        if ($this->_request->isPost()) {
            try {
                $post = $this->_request->getPost();

                //редактирование через внешнбб форму (jqGrid)
                if ($outerEdit) {
                    $post = $this->_helper->utils->addPrefix($post, 'object');
                }

                if ($form->isValid($post)) {

                    $editMode = $form->getEditMode();

                    $values = $form->getValues();
                    $values = $this->_helper->utils->stripPrefix($values, 'object');
                    $attrs = $this->_helper->utils->arrayStraighten($attrs, 'id', 2);

                    //ID основной категории
                    if (!$multiCategories) {
                        $values['category_id'] = $objectCategory->getId();
                    } else {
                        unset($values[$reqParamCategory]);
                    }

                    //массив полей объекта и массив значений атрибутов
					$attrFiles = array();
					$attrValues = array();
                    $objectValues = array();

                    //значение полей и атрибутов
					foreach ($values as $key => $value) {
						if ($key == $attrPrefix) {
                            $attrValues = $value;
						} else {
							$objectValues[$key] = $value;
						}
					}

					//файловые атрибуты
					if ($uploadFiles) {
						$files = $this->_helper->fileTransfer();
						foreach ($files as $key => $info) {
							$attrId = $form->getFieldId($key);
							$attrFiles[$attrId] = $info;
						}
					}

					//создаем новый объект
                    $object = Catalogue_Model_Object::create($objectValues);

					//привяжем объект к категории
                    $object->addCategories($objectCategories);

                    //добавляем значения атрибутов
					if (!empty($attrValues)) {
                        $object->addAttrValues($attrValues, $attrs);
					}

					if (!empty($attrFiles)) {
						$object->addFiles($attrFiles);
					}

                    $object->save();

                    //редирект на страницу списка объектов
                    if (!$this->_request->isXmlHttpRequest()) {

                        if ($editMode == Catalogue_Form_Object::APPLY_MODE) {
                            $params = array('id' => $object->getId());

                            if ($refId > 0) {
                               $params['ref'] = $refId;
                            }

                            if ($backurl) {
                                $params['backurl'] = $backurl;
                            }

                            $redirect = $this->_helper->url('edit-object', null, null, $params);

						} elseif ($backurl) {
							$redirect = $backurl;

						} elseif (!$multiCategories && count($categoryIds) == 1) {
                            $redirect = $this->_helper->url('list-object', null, null, array($reqParamCategory => $object->getCategoryId()));

                        } else {
                            $redirect = $this->_helper->url('list-object');
                        }
                        $this->_redirect($redirect);
                    } else {
                        return;
                    }

                }

                throw new Workset_Model_Exception($form->getCustomMessages(Workset_Form::ERROR_CODE), Workset_Form::ERROR_CODE);
            }
            catch (Zend_Exception $e) {
                $this->_helper->application->throwException($e, null, false);
            }
        }

        if (!$outerEdit) {
            $this->view->form = $form;
        }
    }

    //редактирование объекта
    function editObjectAction() {
        $object = $this->_helper->application->getObject('id', true);

		//если отредактировали текущий ID категории
		$categoryId = (int)$this->_request->getPost('nodeid');

        //id категории из URL
		if ($categoryId < 1) {
			$categoryId = (int)$this->_getParam('nodeid');
		}

        $backurl = $this->_getParam('backurl');
        $refId = (int)$this->_getParam('ref', 0);
        if ($refId < 0) {
            $refId = 0;
        }

        $categoryAttrs = $object->getAttributes(null, null, true);
        $attrs = $this->_helper->utils->arrayStraighten($categoryAttrs, 'id', 2);
        $attrValues = $object->getAttrValues();

        $categories = $object->getCategories();
        $attrPrefix = Catalogue_Form_Object::ATTR_PREFIX;
		$uploadFiles = false;

        $objectCategory = $currentObjectCategory = $object->getCategory();

        if ($categoryId > 0 && $categoryId != $object->getCategoryId()) {
            $objectCategory = Catalogue_Model_Category::getInstance($categoryId);
        }

        $oper = $this->_getParam('oper');
        $outerEdit = !empty($oper) && $this->_request->isXmlHttpRequest() ? true : false;

        if ($outerEdit) {
            $this->_helper->viewRenderer->setNoRender(true);
        }

        $formConfig = $this->_helper->moduleConfig('forms/object');
		$form = new Catalogue_Form_Object($formConfig);

        //транслятор формы
        $form->setTranslator(
            $this->_translate,
            $this->_helper->moduleConfig->getConfig(array('lang', $this->_locale, 'validators'), null, true)
        );

		$form->addEditModes(array(
			Catalogue_Form_Object::SAVE_MODE, Catalogue_Form_Object::APPLY_MODE
		));

        $linkedCategories =  $categories->getNewInstance()->setKeyIndex('id');
        $categories = $categories->setKeyIndex('id')->toArray();

        $linkedCategories->remove($currentObjectCategory);
        $linkedCategories = $linkedCategories->toArray('name');

		foreach ($linkedCategories as $key => $value) {
			$object->setParam('linked_categories', array($key => $value));
		}

		//список атрибутов из удаленных категорий
        $hiddenAttrsId = array_diff(array_keys($attrValues), array_keys($attrs));
		if ($hiddenAttrsId) {
			$hiddenAttrs = Catalogue_Model_Attribute::getAll(array(
				"id in(?)" => $hiddenAttrsId
			))->setKeyIndex('id');

            $categoryAttrs[] = $hiddenAttrs;
            foreach ($hiddenAttrs as $attr) {
                $attr->setParam('disabled', true);
                $attr->setParam('delete_url', $this->_helper->url('delete-attr-value', null, null, array(
                    'id' => $object->getId(),
                    'attr_id' => $attr->getId()
                )));
                $attrs[$attr['id']] = $attr;
            }
		}

		//сохраненные значения атрибутов
        foreach ($categoryAttrs as $categoryId => $groupAttrs) {

            $form->addAttrFieldGroup($categories[$categoryId]['code'], null, array(
                'legend' => isset($categories[$categoryId]['name']) ? $categories[$categoryId]['name'] : 'object'
            ));

            foreach ($groupAttrs as $id => $attr) {

                $value = Catalogue_Model_Object::getFormAttrValue($attr, $attrValues);

                $form->addAttrField($attr, $value);
                $form->addAttrToGroup($categories[$categoryId]['code'], $attr);

                if ($attr->isMultiple() && !$attr->isEnum()) {
                    $form->addAttrFieldButton($attr, 'add');
					$form->addAttrFieldButton($attr, 'del');
                }

				if ($attr->isFile()) {
                    if (!$uploadFiles) {
                        $uploadFiles = true;
                    }
                    if (isset($attrValues[$attr->getId()])) {
                        $form->addAttrFieldFileAttachment($attr, $value);
                    }
                }
            }
        }

        if ($this->_request->isPost()) {
			try {
				$post = $this->_request->getPost();

				//редактирование через внешнюю форму (jqGrid)
				if ($outerEdit) {
					$post = $this->_helper->utils->addPrefix($post, 'object');
				}

				//добавим элемент формы с ID категории
				if (isset($post['nodeid'])) {
					$form->setCategory($post['nodeid']);
				}

				if ($form->isValid($post)) {

                    $editMode = $form->getEditMode();

					$values = $form->getValues();
					$values = $this->_helper->utils->stripPrefix($values, 'object');

					//меняем базовую категорию
					if (isset($values['nodeid'])) {
						if (empty($values['nodeid'])) {
							$values['category_id'] = null;
						} else {
							$values['category_id'] = $values['nodeid'];
						}
					}
					elseif (null !== $objectCategory) {
						$values['category_id'] = $objectCategory->getId();
					}

					//массив полей объекта и массив значений атрибутов
					$newAttrFiles = array();
					$newAttrValues = array();
					$objectValues = array();

					foreach ($values as $key => $value) {
						if (isset($object[$key])) {
							$objectValues[$key] = $value;
						}
					}

					if (isset($values[$attrPrefix])) {
						$newAttrValues = $values[$attrPrefix];
					}

					if ($uploadFiles) {
						$files = $this->_helper->fileTransfer();
						foreach ($files as $key => $info) {
							$attrId = $form->getFieldId($key);
							$newAttrFiles[$attrId] = $info;
						}
					}

                    $object->setData($objectValues);

					if ($newAttrValues) {
						$object->addAttrValues($newAttrValues, $attrs);
					}

					if ($newAttrFiles) {
						$object->addFiles($newAttrFiles);
					}

					//смена текущей категории
                    if ($currentObjectCategory && $objectCategory) {
                        if ($currentObjectCategory->getId() != $objectCategory->getId()) {
                            $object->deleteCategory($currentObjectCategory);
                            $object->addCategory($objectCategory);
                        }
                    }
                    //добавления категории
                    elseif (!$currentObjectCategory && $objectCategory) {
                        $object->addCategory($objectCategory);
                    }
					//удаление категории
					elseif ($currentObjectCategory && !$objectCategory) {
						$object->deleteCategory($currentObjectCategory);
					}

					$object->save();

					if (!$this->_request->isXmlHttpRequest()) {

                        if ($editMode == Catalogue_Form_Object::APPLY_MODE) {
                            $params = array('id' => $object->getId());

                            if ($refId > 0) {
                               $params['ref'] = $refId;
                            }

                            if ($backurl) {
                                $params['backurl'] = $backurl;
                            }

                            $redirect = $this->_helper->url('edit-object', null, null, $params);

						} elseif ($backurl) {
							$redirect = $backurl;

                        } elseif ($object->hasCategory()) {
							$redirect = $this->_helper->url('list-object', null, null, array('nodeid' => $object->getCategoryId()));

						} else {
							$redirect = $this->_helper->url('list-object');
						}

						$this->_redirect($redirect);
					} else {
						return;
					}
				} else {
					throw new Workset_Model_Exception($form->getCustomMessages(Workset_Form::ERROR_CODE), Workset_Form::ERROR_CODE);
				}

			} catch (Zend_Exception $e) {
				$this->_helper->application->throwException($e, null, false);
			}
        } else {
            $data = $object->getDisplayData();

            foreach ($data as $key => $value) {
                $key = 'object_'.$key;
                if ($element = $form->getElement($key)) {
                    $element->setValue($value);
                }
            }
        }

        if (!$outerEdit) {
                //редактирование категорий
            if (!empty($this->_actionConfig['edit_category'])) {

                $object->setParam('edit_base_category_url', $this->_helper->url('select-single-category', null, null, array(
                    'nodeid' => $object->getCategoryId(),
                    'backurl' => $this->_request->getRequestUri()
                )));

                $object->setParam('delete_base_category_url', $this->_helper->url('delete-base-category', null, null, array(
                    'id' => $object->getId(),
                    'backurl' => $this->_request->getRequestUri()
                )));

                //ссылка на редактирование связанных категорий
                $object->setParam('edit_linked_categories_url', $this->_helper->url('list-object-category', null, null, array(
                    'id' => $object->getId(),
                    'backurl' => $this->_request->getRequestUri()
                )));

                $object->setParam('delete_linked_category_url', $this->_helper->url('delete-object-category', null, null, array(
                    'id' => $object->getId()
                )));

                $object->setParam('edit_category', true);

            } else {
                $object->setParam('edit_category', false);
            }

            //список связанных категорий
            if (!empty($this->_actionConfig['show_category_list'])) {

                $linkedCategories = $object->getParam('linked_categories');

                if ($linkedCategories) {
                    $object->setParam('linked_categories', implode(", ", $linkedCategories));
                } else {
                    $object->setParam('linked_categories', false);
                }

                $object->setParam('show_category_list', true);

            } else {
                $object->setParam('show_category_list', false);
            }

            $this->view->form = $form;
            $this->view->category = $objectCategory;
            $this->view->object = $object;

            if (!empty($this->_actionConfig['show_category_list'])) {
                $this->render('edit-object');
            }

            $this->render('add-object');
        }
    }

    //удаление объекта
    function deleteObjectAction() {
        $this->_helper->viewRenderer->setNoRender(true);

        $listId = $this->_helper->application->getListId('id', true);
        if (empty($listId)) {
            throw $this->_helper->application->throwException(null, 404);
        }

        $filter = array('id in(?)' => $listId);

        $itemList = Catalogue_Model_Object::getAll($filter);

        try {
            foreach ($itemList as $object) {
                $object->delete();
            }
        } catch (Zend_Exception $e) {
            throw $this->_helper->application->throwException($e);
        }

        if (!$this->_request->isXmlHttpRequest()) {
            $backUrl = $this->_getParam('backurl');

            if ($backUrl) {
                $redirect = $backUrl;
            } else {
                $redirect = $this->_helper->url('list-object');
            }

            $this->_redirect($redirect);
        }
    }

    function listObjectAction() {
        $refId = (int)$this->_getParam('nodeid');
        $refType = $this->_getParam('reftype', 'category');

        $categoryId = 0;
        $category = null;

        $backUrl = '';
        $backUrlLabel = '';

		$tableId = 'objectList';
        $pagerId = 'objectPager';

        if ($refId < 0) {
            $refId = 0;
        }

        //настройки из конфига
        if (!empty($this->_actionConfig['jqgrid_object_edit_url'])) {
            $editUrlParams = $this->_actionConfig['jqgrid_object_edit_url'];
        } else {
            $editUrlParams = array('action' => 'ajax-object-switcher');
        }

        if (!empty($this->_actionConfig['jqgrid_object_model_url'])) {
            $modelUrlParams = $this->_actionConfig['jqgrid_object_model_url'];
        } else {
            $modelUrlParams = array('action' => 'list-object-model');
        }

        if (!empty($this->_actionConfig['jqgrid_back_url_to_category'])) {
            $backUrlToCategoryParams = $this->_actionConfig['jqgrid_back_url_to_category'];
        } else {
            $backUrlToCategoryParams = array('action' => 'list-category');
        }

        if (!empty($this->_actionConfig['jqgrid_back_url_to_object'])) {
            $backUrlToObjectParams = $this->_actionConfig['jqgrid_back_url_to_object'];
        } else {
            $backUrlToObjectParams = array('action' => 'list-object');
        }

        if (!empty($this->_actionConfig['jqgrid_object_category_url'])) {
            $objectCategoryUrlParams = $this->_actionConfig['jqgrid_object_category_url'];
        } else {
            $objectCategoryUrlParams = array('action' => 'list-object-category');
        }

        if (!empty($this->_actionConfig['jqgrid_object_select_url'])) {
            $selectObjectUrlParams = $this->_actionConfig['jqgrid_object_select_url'];
        } else {
            $selectObjectUrlParams = array('action' => 'select-object');
        }

        if (!empty($this->_actionConfig['jqgrid_object_linked_url'])) {
            $linkedObjectUrlParams = $this->_actionConfig['jqgrid_object_linked_url'];
        } else {
            $linkedObjectUrlParams = array('action' => 'list-object');
        }

        if (isset($this->_actionConfig['jqgrid_object_navgrid'])) {
            $gridButtons = (array)$this->_actionConfig['jqgrid_object_navgrid'];
        } else {
            $gridButtons = array(
                'search' => true,
                'edit' => false,
                'add' => false,
            );
        }

        if (isset($this->_actionConfig['jqgrid_object_navgrid_buttons'])) {
            $gridExButtons = (array)$this->_actionConfig['jqgrid_object_navgrid_buttons'];
        } else {
            $gridExButtons = array(
                'b_add' => array(),
                'b_edit' => array(),
                'b_categories' => array(),
                'b_objects' => array(),
                'b_select_objects' => array()
            );
        }

        if ($refId > 0) {
            if ($refType == 'category') {
                $categoryId = $refId;
                $category = $this->_helper->application->getCategory($categoryId);

                if ($category->hasParent()) {
                    $backUrlToCategoryParams['params']['nodeid'] = $category->getParentId();
                }

                $backUrl = $this->_helper->url($backUrlToCategoryParams);

                if (!$this->_navigationInit && !$this->_getParam('navigationInit')) {

                    $category->setUrl('navigation', $backUrl)->setLabel('navigation', $category['name']);
                    $this->_addNavItem($category);
                }

                $this->_layoutPageTitle = $this->_actionConfig['title_object'];
                $backUrlLabel = $this->_actionConfig['backurl_to_category'];

            } elseif ($refType == 'object') {
                $object = $this->_helper->application->getObject($refId);

                if ($object->hasCategory()) {
                    $backUrlToObjectParams['params']['nodeid'] = $object->getCategoryId();
                }

                $backUrl = $this->_helper->url($backUrlToObjectParams);

                $this->_layoutPageTitle = $this->_actionConfig['title_linked_object'];
                $backUrlLabel = $this->_actionConfig['backurl_to_object'];

                if (!$this->_navigationInit && !$this->_getParam('navigationInit')) {

                    $object->setUrl('navigation', $backUrl)->setLabel('navigation', $object['title']);

                    $this->_addNavItem($object);
                    $this->_addNavItem(array(
                        'title' => $this->_layoutPageTitle,
                        'label' => $this->_layoutPageTitle,
                        'uri' => $this->_request->getRequestUri()
                    ));
                }

                $selectObjectUrlParams['params']['id'] = $object->getId();

                if (isset($gridExButtons['b_select_object'])) {
                    $gridExButtons['b_select_object'] = $gridExButtons['b_select_object'] + array(
                            'query' => Zend_Json::encode(array(
                                'id' => $object->getId()
                            )),
                            'position' => 'first'
					    );
                }

                if (isset($gridExButtons['b_add'])) {
                    $gridExButtons['b_add'] = $gridExButtons['b_add'] + array(
						    'active' => false
					    );
                }

            }

            $editUrlParams['params']['nodeid'] = $refId;

            $modelUrlParams['params']['nodeid'] = $refId;
            $modelUrlParams['params']['reftype'] = $refType;

        }

        $modelUrl = $this->_helper->url($modelUrlParams);
        $editUrl = $this->_helper->url($editUrlParams);

        $gridOptions = array(
            'caption' => $this->_actionConfig['jqgrid_object_caption'],
            'url' => $modelUrl,
            'mtype' => 'GET',
            'colNames' => array_values($this->_actionConfig['jqgrid_object_col_names']),
            'colModel' => array_values($this->_actionConfig['jqgrid_object_col_model']),
            'sortname' => 'id',
            'sortorder' => "desc",
            'viewrecords' => true,
            'multiselect' => true,
            'editurl'   => $editUrl,
            'autowidth' => true,
            'rowNum' => 20,
            'viewsortcols' => array('code', 'title', 'id'),
        );

        $jqgrid = $this->view->JQueryGrid();

        //subgrid
        if (!empty($this->_actionConfig['jqgrid_subgrid'])) {
            $gridOptions['subGrid'] = true;

            if (!empty($this->_actionConfig['jqgrid_subgrid_row_expand_func'])) {
                $gridOptions['subGridRowExpanded'] = new Zend_Json_Expr($this->_actionConfig['jqgrid_subgrid_row_expand_func']);
            } else {
                $gridOptions['subGridRowExpanded'] = new Zend_Json_Expr($this->_helper->application->jsFunction('expand', array('subgrid_id', 'row_id'), true));
            }

            if (!empty($this->_actionConfig['jqgrid_subgrid_row_colapse_func'])) {
                $gridOptions['subGridRowColapsed'] = new Zend_Json_Expr($this->_actionConfig['jqgrid_subgrid_row_colapse_func']);
            } else {
                $gridOptions['subGridRowColapsed'] = null;
            }

            if (!empty($this->_actionConfig['jqgrid_subgrid_model_url'])) {
                $jqgrid->invokeParams(array('subgridUrl' => $this->_helper->url($this->_actionConfig['jqgrid_subgrid_model_url'])));
            } else {
                $jqgrid->invokeParams(array('subgridUrl' => $this->_helper->url('list-object-attr-model')));
            }
        }

        //URL для редактирования
		$uri = $this->_helper->httpUri($editUrl);
        $uri->setQuery(null);
        $editUrl = $uri->getUri();

        //URL для кнопок навигации
		if ($categoryId > 0) {
			$listParams = array('nodeid' => $categoryId);
		} else {
			$listParams = array('backurl' => $this->_request->getRequestUri());
		}

        //параметры для добавления
		$addParams = array_merge($listParams, array('oper' => 'add', 'ref' => $refId));

        //параметры для редактирования
        $editParams = array_merge($listParams, array('oper' => 'edit', 'ref' => $refId));

        //параметры списка связанных объектов
        $linkedObjectParams = array_merge($listParams, array('reftype' => 'object'));

        if (isset($gridExButtons['b_add'])) {
            $gridExButtons['b_add'] += array(
                'caption' => false,
                'title' => false,
				'active' => true,
				'path' => $editUrl,
				'query' => Zend_Json::encode($addParams),
				'grid_id' => $tableId,
				'position' => 'first',
			);
        }

        if (isset($gridExButtons['b_edit'])) {
            $gridExButtons['b_edit'] += array(
                'caption' => false,
                'title' => false,
                'active' => true,
                'path' => $editUrl,
                'query' => Zend_Json::encode($editParams),
                'grid_id' => $tableId,
                'position' => 'last',
			);
        }

        if (isset($gridExButtons['b_categories'])) {
            $gridExButtons['b_categories'] += array(
                'caption' => false,
                'title' => false,
                'active' => true,
                'path' => $this->_helper->url($objectCategoryUrlParams),
                'query' => Zend_Json::encode($listParams),
                'grid_id' => $tableId,
                'position' => 'last',
			);
        }

        if (isset($gridExButtons['b_objects'])) {
            $gridExButtons['b_objects'] += array(
                'caption' => false,
                'title' => false,
                'active' => true,
                'path' => $this->_helper->url($linkedObjectUrlParams),
                'query' => Zend_Json::encode($linkedObjectParams),
                'grid_id' => $tableId,
                'position' => 'last',
			);
        }

        if (isset($gridExButtons['b_select_objects'])) {
            $gridExButtons['b_select_objects'] += array(
                'caption' => false,
                'title' => false,
                'active' => true,
                'path' => $this->_helper->url($selectObjectUrlParams),
                'query' => Zend_Json::encode($listParams),
                'grid_id' => $tableId,
                'position' => 'last',
            );
        }

        //ссылка на объект помошника
        $jqgrid->setTableId($tableId)
			   ->setPagerId($pagerId)
			   ->setOptions($gridOptions)
			   ->enableNavGrid($gridButtons);

        $this->view->grid = $jqgrid;

		$this->view->gridButtons = $gridExButtons;
        $this->view->category = $category;
        $this->view->backurl = $backUrl;
        $this->view->backurlLabel = $backUrlLabel;
        $this->view->jsObject = $this->_helper->application->jsFunctionName();

        if (!empty($this->_actionConfig['view_script'])) {
            $this->render($this->_actionConfig['view_script']);
        }

    }

    function listObjectModelAction() {
        $this->_helper->viewRenderer->setNoRender(true);

        $refId = (int)$this->_getParam('nodeid');
        $refType = $this->_getParam('reftype', 'category');
        $page = (int)$this->_getParam('page');
        $diffId = (int)$this->_getParam('diff');
        $intersectId = (int)$this->_getParam('intersect');

        if ($page < 1) {
           $page = 1;
        }

        $rows = (int)$this->_getParam('rows');
        if ($rows < 1) {
            $rows = Workset_Model_Object_Abstract::ROWS_LIMIT;
        }

        $order = $this->_helper->application->getSortOrder();

        $jqGrid = $this->_helper->JQueryGrid;
        $jqGrid->addColumnFormatter('created', function($value) {
            return timestampToDatetime($value);
        });

        $filter = $this->_getParam('filters');
        $filter = $jqGrid->getFilter($filter, $this->_actionConfig['jqgrid_object_col_model']);

        if ($refId > 0 && $refType == 'object') {

            $object = Catalogue_Model_Object::getInstance($refId);
            $itemList = $object->getObjects($filter, $order, $rows, $page, true);

        } elseif ($refId > 0 && $refType == 'category') {

            $objectId = $diffId > 0 ? $diffId
                                    : ($intersectId > 0 ? $intersectId : 0);

            if ($objectId > 0) {
                $object = Catalogue_Model_Object::getInstance($objectId);
                $listId = array_values($object->getObjects()->toArray('id'));
                $listId[] = $object->getId();

                $filter[$intersectId > 0 ? 'id in(?)' : 'id not in(?)'] = $listId;
            }

			$itemList = Catalogue_Model_Object::getAllByCategory($refId, $filter, $order, $rows, $page, true);
        } else {
			$itemList = Catalogue_Model_Object::getAll($filter, $order, $rows, $page, true);
		}

        foreach ($itemList as $key => $item) {
            $itemCategories = $item->getCategories()->setKeyIndex('id')->toArray('name');
            $categories = implode(', ', $itemCategories);

            $item->setParam('categories', $categories)
                 ->setParam('categoriesId', array_keys($itemCategories));
        }

        $records = $jqGrid->getRecords(
            $itemList, $page, ceil($itemList->getTotalCount() / $rows),
            $itemList->getTotalCount(), array(
                'code', 'title', 'created', 'updated', 'status', 'categories', 'id', 'categoriesId'
            )
        );

        $this->_helper->json($records, true);
    }

    function selectObjectAction() {
        $object = $this->_helper->application->getObject('id', true);

		$backUrl = $this->_getParam('backurl');
		$categoryId = (int)$this->_getParam('category_id');
		$categoryPagerId = 'category_pager';
		$categoryTableId = 'category_grid';
		$linkedObjectPagerId = 'object_pager';
		$linkedObjectTableId = 'object_grid';

		$categoryModelUrl = $this->_helper->url('list-category-model');

		if ($categoryId > 0) {
			$category = $this->_helper->application->getCategory($categoryId);
		} else {
			$category = null;
		}

		if (!$backUrl) {
			if ($object->hasCategory()) {
				$backUrl = $this->_helper->url('list-object', null, null, array('nodeid' => $object->getCategoryId()));
			} else {
				$backUrl = $this->_helper->url('list-object');
			}
		}

        $categoryGridOptions = array(
            'caption' => 'Доступные категории',
            'url' => $categoryModelUrl,
            'mtype' => 'GET',
            'colNames' => array_values($this->_actionConfig['jqgrid_category_col_names']),
            'colModel' => array_values($this->_actionConfig['jqgrid_category_col_model']),
            'sortname' => 'id',
            'sortorder' => "desc",
            'viewrecords' => true,
			'treeGrid' => true,
            'treeGridModel' => 'adjacency',
            'treedatatype' => 'json',
            'ExpandColumn' => 'name',
            'ExpandColClick' => true,
            'autowidth' => false,
            'rowNum' => 50,
            'viewsortcols' => array('name', 'display_title', 'code', 'id'),
            'height' => 400,
            'width' => 580,
            'pager' => '#'.$categoryPagerId,
			'ondblClickRow' => $this->_helper->application->jsFunction('listObject', array('objectId' => $object->getId(), 'event'), true, true),
			'afterInsertRow' => null
        );

        $objectGridOptions = array(
            'caption' => 'Доступные объекты',
            'url' => 	( $categoryId > 0
							? $this->_helper->url('list-object-model', null, null, array('nodeid' => $categoryId, 'diff' => $object->getId()))
							: $this->_helper->url('list-object-model')
						),
            'mtype' => 'GET',
            'colNames' => array_values($this->_actionConfig['jqgrid_object_col_names']),
            'colModel' => array_values($this->_actionConfig['jqgrid_object_col_model']),
            'sortname' => 'id',
            'sortorder' => "desc",
            'viewrecords' => true,
            'multiselect' => false,
            'editurl'   => '',
            'autowidth' => false,
            'height' => 400,
            'width' => 580,
            'rowNum' => 50,
            'pager' => '#'.$categoryPagerId,
            'viewsortcols' => array('code', 'title', 'id'),
            'ondblClickRow' => $this->_helper->application->jsFunction('addObject', array(
                'objectId' => $object->getId(),
                'url' => $this->_helper->url('add-linked-object'),
                'rowId', 'rowIndex', 'event'
            ), true, true),
			'afterInsertRow' => null
        );

        $linkedObjectGridOptions = array_merge($objectGridOptions, array(
			'pager' => '#'.$linkedObjectPagerId,
            'caption' => 'Связанные объекты',
            'url' => $this->_helper->url('list-object-model', null, null, array('nodeid' => $object->getId(), 'reftype' => 'object')),
            'ondblClickRow' => $this->_helper->application->jsFunction('deleteObject', array(
                'objectId' => $object->getId(),
                'url' => $this->_helper->url('delete-linked-object'),
                'rowId', 'rowIndex', 'event'
            ), true, true),
        ));

        //таблица списка всех категорий
        $categoryGrid = $this->view->JQueryGrid();

        //таблица списка объектов из выбранной категории
        $objectGrid = $categoryGrid->getNewInstance();

        //таблица списка текущий связанных объектов
        $linkedObjectGrid = $categoryGrid->getNewInstance();

        $categoryGrid->setTableId($categoryTableId)
             ->setPagerId($categoryPagerId)
             ->setOptions($categoryGridOptions)
             ->enableNavGrid(array(
                'all' => false
            ))
             ->addNavButton('list_object', array(
                'buttonicon' => 'ui-icon-arrowthick-1-s',
                'caption' => 'объекты',
                'position' => 'first',
                'onClickButton' => $this->_helper->application->jsFunction('listObject', array('objectId' => $object->getId(), 'event'), true, true)
            ));

        $objectGrid->setTableId($categoryTableId)
           ->setPagerId($categoryPagerId)
           ->setOptions($objectGridOptions)
           ->enableNavGrid(array(
                'all' => false, 'refresh' => true
            ))
            ->addNavButton('list_category', array(
                'buttonicon' => 'ui-icon-arrowthick-1-w',
                'caption' => 'категории',
                'position' => 'first',
                'onClickButton' => $this->_helper->application->jsFunction('listCategory', array('objectId' => $object->getId(), 'event'), true, true)
            ));

        $linkedObjectGrid->setTableId($linkedObjectTableId)
            ->setPagerId($linkedObjectPagerId)
            ->setOptions($linkedObjectGridOptions)
            ->enableNavGrid(array(
                'all' => false, 'refresh' => true
            ));

        $this->view->categoryGrid = $categoryGrid;
        $this->view->objectGrid = $objectGrid;
        $this->view->linkedObjectGrid = $linkedObjectGrid;

        $this->view->object = $object;
        $this->view->category = $category;
        $this->view->jsObject = $this->_helper->application->jsFunctionName();

		$this->view->backurl = $backUrl;
        $this->view->backurlLabel = $this->_actionConfig['backurl_label'];

    }

    //привязывает объект к категории
    function addObjectCategoryAction() {
        $this->_helper->viewRenderer->setNoRender(true);

        $object = $this->_helper->application->getObject('id', true);
        $category = $this->_helper->application->getCategory('nodeid', true);

        //проверка на привязку к конечным листьям
        if ($this->_actionConfig['link_to_deep_category_only'] && $category->hasChilds()) {
            throw $this->_helper->application->throwException(null, 500);
        }

        try {

			//добавляем категорию в конец списка
			$data = array('priority' => $object->getMaxCategoryPriority() + 1);
            $object->linkToObject($category, $data);

        } catch (Zend_Exception $e) {
            throw $this->_helper->application->throwException(null, 500);
        }

        if (!$this->_request->isXmlHttpRequest()) {
            $redirect = $this->_getParam('backurl');
            if (!$redirect) {
                $redirect = $this->_helper->url('list-object', null, null, array(
                    'nodeid' => $object->getCategoryId()
                ));
            }
            $this->_redirect($redirect);
        }
    }

    //удаляет объект из категории
    function deleteObjectCategoryAction() {
        $this->_helper->viewRenderer->setNoRender(true);

        $object = $this->_helper->application->getObject('id', true);
        $categoryId = (int)$this->_getParam('nodeid');

		if ($categoryId < 1) {
			$categories = $object->getCategories();
		} else {
            $category = $this->_helper->application->getCategory($categoryId);
			$categories = array($category);
		}

        try {

			$observer = new Catalogue_Model_Object_Observer_CategoryPriority();
			$object->attach($observer);

            foreach ($categories as $category) {
                if ($category->getId() == $object->getCategoryId()) {
                    continue;
                }

                $object->unlinkObject($category);
            }
        } catch (Zend_Exception $e) {
            throw $this->_helper->application->throwException(null, 500);
        }

        if (!$this->_request->isXmlHttpRequest()) {
            $redirect = $this->_getParam('backurl');
            if (!$redirect) {
                $redirect = $this->_helper->url('list-object', null, null, array(
                    'nodeid' => $object->getCategoryId()
                ));
            }
            $this->_redirect($redirect);
        }
    }

    function sortObjectCategoryAction() {
        $this->_helper->viewRenderer->setNoRender(true);

        $index = (int)$this->_getParam('index');
        if ($index < 1) {
            throw $this->_helper->application->throwException(null, 500);
        }

		$object = $this->_helper->application->getObject('id', true);
        $category = $this->_helper->application->getCategory('nodeid', true);

        $object->setCategoryPriority($category, $index);

        if (!$this->_request->isXmlHttpRequest()) {
            $redirect = $this->_getParam('backurl');
            if (!$redirect) {
                $redirect = $this->_helper->url('list-object', null, null, array(
                    'nodeid' => $object->getCategoryId()
                ));
            }
            $this->_redirect($redirect);
        }

    }

	function deleteBaseCategoryAction() {
		$this->_helper->viewRenderer->setNoRender(true);

		$object = $this->_helper->application->getObject('id', true);

		if ($object['category_id'] > 0) {
            $categoryId = $object['category_id'];
			$object['category_id'] = null;

            try {

                $object->deleteCategory($categoryId)->save();

            } catch (Zend_Exception $e) {
                throw $this->_helper->application->throwException(null, 500);
            }
		}

		if (!$this->_request->isXmlHttpRequest()) {
            $redirect = $this->_getParam('backurl');
            if (!$redirect) {
                $redirect = $this->_helper->url('list-object', null, null, array(
                    'nodeid' => $object->getCategoryId()
                ));
            }
            $this->_redirect($redirect);
        }
	}

    function addLinkedObjectAction() {
        $this->_helper->viewRenderer->setNoRender(true);

		$object = $this->_helper->application->getObject('id', true);

        $references = $this->_helper->application->getListId('nodeid', true);

        if (empty($references)) {
            throw $this->_helper->application->throwException(null, 500);
        }

        try {

            $object->addObjects($references)->save();

        } catch (Zend_Exception $e) {
            throw $this->_helper->application->throwException(null, 500);
        }

        if (!$this->_request->isXmlHttpRequest()) {
            $redirect = $this->_getParam('backurl');
            if (!$redirect) {
                $redirect = $this->_helper->url('list-object', null, null, array(
                    'nodeid' => $object->getCategoryId()
                ));
            }
            $this->_redirect($redirect);
        }
    }

    function deleteLinkedObjectAction() {
        $this->_helper->viewRenderer->setNoRender(true);

		$object = $this->_helper->application->getObject('id', true);

        $references = $this->_helper->application->getListId('nodeid', true);
        if (empty($references)) {
            throw $this->_helper->application->throwException(null, 500);
        }

        try {

            $object->deleteObjects($references)->save();

        } catch (Zend_Exception $e) {
            throw $this->_helper->application->throwException(null, 500);
        }

        if (!$this->_request->isXmlHttpRequest()) {
            $redirect = $this->_getParam('backurl');
            if (!$redirect) {
                $redirect = $this->_helper->url('list-object', null, null, array(
                    'nodeid' => $object->getCategoryId()
                ));
            }
            $this->_redirect($redirect);
        }
    }

	function deleteAttrValueAction() {
		$this->_helper->viewRenderer->setNoRender(true);

		$object = $this->_helper->application->getObject('id', true);

		$attr = $this->_helper->application->getAttribute('attr_id', true);
		if (!$attr) {
			throw $this->_helper->application->throwException(null, 404);
		}

        $valueId = (int)$this->_getParam('value_id');
        if ($valueId < 1) {
            $valueId = null;
        }

        try {

            $object->deleteAttrValue($attr, $valueId)->save();

        } catch (Zend_Exception $e) {
            throw $this->_helper->application->throwException(null, 500);
        }

        if (!$this->_request->isXmlHttpRequest()) {
            $redirect = $this->_getParam('backurl');
            if (!$redirect) {
                $redirect = $this->_helper->url('edit-object', null, null, array(
                    'nodeid' => $object->getCategoryId(),
					'id' => $object->getId()
                ));
            }
            $this->_redirect($redirect);
        }
	}

    function listObjectAttrModelAction() {
        $object = $this->_helper->application->getObject('id', true);

        $attrValues = $object->getAttrValues();

        $records = array();

        //ID атрибутов
        $attrIds = array();

        foreach ($attrValues as $value) {
            $attrIds[] = $value['attr_id'];
        }

        $attrList = Catalogue_Model_Attribute::getAll(array('id in(?)' => $attrIds))
                    ->setKeyIndex('id')->toArray('name');

        foreach ($attrValues as $value) {
            $records[] = array(
                'value' => $value['value'],
                'name' => $attrList[$value['attr_id']]
            );
        }

        $this->_helper->json($records, true);
        //echo Zend_Json::encode($records);
    }

    //список категорий объектов
    function listObjectCategoryAction() {
        $object = $this->_helper->application->getObject('id', true);

        $categoryId = (int)$this->_getParam('nodeid');
		$backUrl = $this->_getParam('backurl');

		if (!$backUrl) {
			if ($categoryId > 0) {
				$backUrl = $this->_helper->url('list-object', null, null, array('nodeid' => $categoryId));
			} else {
				$backUrl = $this->_helper->url('list-object');
			}
		}

        if (!empty($this->_actionConfig['jqgrid_visible_category_col_model'])) {
            $this->_actionConfig['jqgrid_category_col_model'] = array_intersect_key($this->_actionConfig['jqgrid_category_col_model'], array_flip($this->_actionConfig['jqgrid_visible_category_col_model']));
            $this->_actionConfig['jqgrid_category_col_names'] = array_intersect_key($this->_actionConfig['jqgrid_category_col_names'], array_flip($this->_actionConfig['jqgrid_visible_category_col_model']));
        }

        $this->_actionConfig['jqgrid_category_col_model'] = array_values($this->_actionConfig['jqgrid_category_col_model']);
        $this->_actionConfig['jqgrid_category_col_names'] = array_values($this->_actionConfig['jqgrid_category_col_names']);

        $allCategoriesModelUrl = $this->_helper->url('ajax-list-category-switcher', null, null, array(
            'oper' => 'ignore_object_categories', 'id' => $object->getId(),
            'cols' => implode(',', $this->_helper->utils->arrayValues($this->_actionConfig['jqgrid_category_col_model'], 'index', 1))
        ));
        $objCategoriesModelUrl = $this->_helper->url('list-object-category-model', null, null, array(
            'id' => $object->getId(),
            'cols' => implode(',', $this->_helper->utils->arrayValues($this->_actionConfig['jqgrid_category_col_model'], 'index', 1))
        ));

        $addCategoryUrl = $this->_helper->url('add-object-category');
        $deleteCategoryUrl = $this->_helper->url('delete-object-category');

		$objCategoriesTableId = 'objList';
        $allCategoriesTableId = 'allList';

        $allCategoriesPagerId = 'allPager';
        $objCategoriesPagerId = 'objPager';

        $objCategoriesGridOptions = array(
            'caption' => 'Выбранные категории',
            'url' => $objCategoriesModelUrl,
            'mtype' => 'GET',
            'colNames' => $this->_actionConfig['jqgrid_category_col_names'],
            'colModel' => $this->_actionConfig['jqgrid_category_col_model'],
            'sortname' => 'id',
            'sortorder' => "desc",
            'viewrecords' => true,
            'autowidth' => false,
            'rowNum' => 100,
            'viewsortcols' => array(),
            'height' => 300,
			'width' => 550,
			'ondblClickRow' => new Zend_Json_Expr('
				function(rowid) {
					return '.$this->_helper->application->jsFunction('objectDblClickRow', array(
						'objectId' => $object->getId(),
						'url' => $deleteCategoryUrl,
						'rowid'
					)).'
				}
			'),
            'gridComplete' => new Zend_Json_Expr(
                $this->_helper->application->jsFunction('objectGridComplete', array(
                    'objectId' => $object->getId(),
                    'url' => $this->_helper->url('sort-object-category')
                ), true)
            )
        );

        $allCategoriesGridOptions = array(
            'caption' => 'Доступные категории',
            'url' => $allCategoriesModelUrl,
            'mtype' => 'GET',
            'colNames' => $this->_actionConfig['jqgrid_category_col_names'],
            'colModel' => $this->_actionConfig['jqgrid_category_col_model'],
            'sortname' => 'id',
            'sortorder' => "desc",
            'viewrecords' => true,
			'treeGrid' => true,
            'treeGridModel' => 'adjacency',
            'treedatatype' => 'json',
            'ExpandColumn' => 'name',
            'ExpandColClick' => true,
            'autowidth' => false,
            'rowNum' => 100,
            'viewsortcols' => array('name', 'code', 'id'),
            'height' => 300,
			'width' => 580,
			'ondblClickRow' => new Zend_Json_Expr('
				function(rowid) {
					return '.$this->_helper->application->jsFunction('listDblClickRow', array(
						'objectId' => $object->getId(),
						'url' => $addCategoryUrl,
						'rowid'
					)).'
				}
			'),
        );

        //таблица списка всех категорий
        $allGrid = $this->view->JQueryGrid();

        //таблица списка категорий объекта
        $objGrid = $allGrid->getNewInstance();

        $allGrid->setTableId($allCategoriesTableId)
				->setPagerId($allCategoriesPagerId)
				->setOptions($allCategoriesGridOptions)
				->gridComplete(false)
                ->enableNavGrid(array(
                    'all' => false,
                    'refresh' => true
                ));


        $objGrid->setTableId($objCategoriesTableId)
                ->setPagerId($objCategoriesPagerId)
				->setOptions($objCategoriesGridOptions)
				->gridComplete(false)
                ->enableNavGrid(array(
                    'all' => false,
                    'refresh' => true
                ));

        $this->view->objectGrid = $objGrid;
        $this->view->allGrid = $allGrid;
        $this->view->backurl = $backUrl;
        $this->view->object = $object;
        $this->view->jsObject = $this->_helper->application->jsFunctionName();
        $this->view->backurlLabel = $this->_actionConfig['backurl_label'];
    }

    //список категорий объекта
    function listObjectCategoryModelAction() {
        $object = $this->_helper->application->getObject('id', true);

        $cols = $this->_helper->application->getList('cols', true);

        $filter = array();

        if ($object->getCategoryId() > 0) {
            $filter['m.id != ?'] = $object->getCategoryId();
        }

        $categoryList = $object->getCategories($filter)->setKeyIndex('id')->toArray();

        $colNames = $this->_helper->utils->arrayValues(
            $this->_actionConfig['jqgrid_category_col_model'], 'index', 1
        );

        if ($cols) {
            $cols = array_intersect($colNames, $cols);
        } else {
            $cols = $colNames;
        }

        $records = $this->_helper->JQueryGrid($categoryList, 1, 1, 1, $cols);

        $this->_helper->json($records, true);
        //echo Zend_Json::encode($records);
    }

    function ajaxCategorySwitcherAction() {
        $this->_helper->viewRenderer->setNoRender(true);

        $actionSwitcher = new Workset_Controller_Plugin_ActionSwitcher('oper', array(
            'del' => array(
                'action' => 'delete-category',
            ),
            'edit' => array(
                'action' => 'edit-category'
            ),
            'add' => array(
                'action' => 'add-category'
            ),
            'object_categories' => array(
                'action' => 'list-category-model',
                'params' => array()
            )
        ));

        $this->getFrontController()->registerPlugin($actionSwitcher);
        $this->_setParam('handlePostDispatch', false);

    }

    function ajaxListCategorySwitcherAction() {
        $this->_helper->viewRenderer->setNoRender(true);

        $operation = $this->_getParam('oper');
        $params = array_intersect_key(
            $this->_request->getParams(),
            array_flip(array(
                'id', 'cols', 'oper', 'ref'
            ))
        );

        switch ($operation) {
            case 'ignore_object_categories':
                $object = $this->_helper->application->getObject('id', true);
                if (!$object) {
                    return;
                }

                $categories = $object->getCategories()->toArray('id');
                $categories = array_values($categories);

                //передаем внутренние параметры для фильтра
                $params['diff'] = $categories;

            break;
        }

        $actionSwitcher = new Workset_Controller_Plugin_ActionSwitcher('oper', array(
            'ignore_object_categories' => array(
                'action' => 'list-category-model',
                'params' => $params,
            )
        ));

        $this->getFrontController()->registerPlugin($actionSwitcher);
        $this->_setParam('handlePostDispatch', false);
    }

    function ajaxAttrSwitcherAction() {
        $this->_helper->viewRenderer->setNoRender(true);

        $actionSwitcher = new Workset_Controller_Plugin_ActionSwitcher('oper', array(
            'del' => array(
                'action' => 'delete-attr',
            ),
            'edit' => array(
                'action' => 'edit-attr'
            ),
            'add' => array(
                'action' => 'add-attr'
            )
        ));

        $this->getFrontController()->registerPlugin($actionSwitcher);
        $this->_setParam('handlePostDispatch', false);
    }

    function ajaxAttrItemSwitcherAction() {
        $this->_helper->viewRenderer->setNoRender(true);

        $actionSwitcher = new Workset_Controller_Plugin_ActionSwitcher('oper', array(
            'del' => array(
                'action' => 'delete-attr-item',
            ),
            'edit' => array(
                'action' => 'edit-attr-item'
            ),
            'add' => array(
                'action' => 'add-attr-item'
            )
        ));

        //для отключения стандартого редиректа через http
        //$actionSwitcher->doHttpRedirect(false);

        //Установка кода редиректа
        //$actionSwitcher->setHttpRedirectCode(302);

        //Отключить проверку прав для следующего действия
        /*
            Zend_Registry::set('actionConfig', array(
                'access_checked' => true
            ));
        */

        $this->getFrontController()->registerPlugin($actionSwitcher);

        //для отключения обработки postDispatch текущего действия
        $this->_setParam('handlePostDispatch', false);
    }

    function ajaxObjectSwitcherAction() {

        $this->_helper->viewRenderer->setNoRender(true);

        $redirectParams = array('nodeid', 'id', 'backurl', 'ref');
		$params = $this->_request->getQuery();
        if (!empty($params)) {
            $params = array_intersect_key($params, array_combine($redirectParams, $redirectParams));
        }

        $actionSwitcher = new Workset_Controller_Plugin_ActionSwitcher('oper', array(
            'del' => array(
                'action' => 'delete-object',
                'params' => $params
			),
            'edit' => array(
                'action' => 'edit-object',
                'params' => $params
            ),
			'add' => array(
				'action' => 'add-object',
				'params' => $params
			)
        ));

        $this->getFrontController()->registerPlugin($actionSwitcher);
        $this->_setParam('handlePostDispatch', false);
    }

}

?>